python实现IQA图像质量评价

231次阅读
没有评论

共计 3981 个字符,预计需要花费 10 分钟才能阅读完成。

提醒:本文最后更新于 2024-08-27 10:40,文中所关联的信息可能已发生改变,请知悉!

全称:Image Quality Assessment

百度百科 IQA:https://baike.baidu.com/item/IQA/19453034?fr=aladdin

python 实现 IQA 图像质量评价

主观评价

主观评价方法主要可分为两种:绝对评价和相对评价。

但是实现起来都有困难,这里先不考虑。

客观评价

全参考

基于图像像素统计基础
  • 峰值信噪比(PSNR):PSNR 值越大,表明待评图像与参考图像之间的失真较小,图像质量较好
  • 均方误差(MSE):MSE 的值越小,表明图像质量越好
代码示例
import cv2 as cv
import numpy as np
import math

# 均方误差(MSE):MSE 的值越小,表明图像质量越好
def get_mse(img1, img2):
    return np.mean((img1 / 255. - img2 / 255.) ** 2)

# 峰值信噪比(PSNR):PSNR 值越大,表明待评图像与参考图像之间的失真较小,图像质量较好
# 基准为 30dB,小于 30 为劣质
def get_psnr(img1, img2):
    mse = get_mse(img1, img2)
    if mse < 1.0e-10:
        return 100
    pixel_max = 1
    return 20 * math.log10(pixel_max / math.sqrt(mse))

if __name__ == '__main__':
    origin_img = cv.imread('img.png', 1)
    new_img = cv.imread('denoised_img_noise.png', 1)
    print('MSE:', get_mse(origin_img, new_img))
    print('PSNR:', get_psnr(origin_img, new_img))
结果

MSE: 0.0004777804926332579

PSNR: 33.20771586094474

从结果可以看出,上面测试使用的降噪后的图片质量还是可以的

基于信息论基础

基于信息论中信息熵基础,互信息被广泛用来评价图像质量。近些年,Sheikh 和 Bovik 等人提出来了信息保真度准则(Information Fidelity Criterion,IFC)和视觉信息保真度(Visual Information Fidelity,VIF)两种算法。它们通过计算待评图像与参考图像之间的互信息来衡量待评图像的质量优劣。这两种方法具有一定的理论支撑,在信息保真度上拓展了图像与人眼之间的联系,但是这类方法对于图像的结构信息没有反应。

关于信息保真度准则(Information Fidelity Criterion,IFC)和视觉信息保真度(Visual Information Fidelity,VIF)这两种算法网上很难搜到合适的资料,即便能找到个别也都是 matlab 的,IFC 方法到现在还没办法实现,下面是 VIF 方法。

代码示例
import numpy
import scipy.signal
import scipy.ndimage

__all__ = ['compare_vifp']

def compare_vifp(ref, dist):
    sigma_nsq = 2
    eps = 1e-10

    num = 0.0
    den = 0.0
    for scale in range(1, 5):

        N = 2 ** (4 - scale + 1) + 1
        sd = N / 5.0

        if scale > 1:
            ref = scipy.ndimage.gaussian_filter(ref, sd)
            dist = scipy.ndimage.gaussian_filter(dist, sd)
            ref = ref[::2, ::2]
            dist = dist[::2, ::2]

        mu1 = scipy.ndimage.gaussian_filter(ref, sd)
        mu2 = scipy.ndimage.gaussian_filter(dist, sd)
        mu1_sq = mu1 * mu1
        mu2_sq = mu2 * mu2
        mu1_mu2 = mu1 * mu2
        sigma1_sq = scipy.ndimage.gaussian_filter(ref * ref, sd) - mu1_sq
        sigma2_sq = scipy.ndimage.gaussian_filter(dist * dist, sd) - mu2_sq
        sigma12 = scipy.ndimage.gaussian_filter(ref * dist, sd) - mu1_mu2

        sigma1_sq[sigma1_sq < 0] = 0
        sigma2_sq[sigma2_sq < 0] = 0

        g = sigma12 / (sigma1_sq + eps)
        sv_sq = sigma2_sq - g * sigma12

        g[sigma1_sq < eps] = 0
        sv_sq[sigma1_sq < eps] = sigma2_sq[sigma1_sq < eps]
        sigma1_sq[sigma1_sq < eps] = 0

        g[sigma2_sq < eps] = 0
        sv_sq[sigma2_sq < eps] = 0

        sv_sq[g < 0] = sigma2_sq[g < 0]
        g[g < 0] = 0
        sv_sq[sv_sq <= eps] = eps

        num += numpy.sum(numpy.log10(1 + g * g * sigma1_sq / (sv_sq + sigma_nsq)))
        den += numpy.sum(numpy.log10(1 + sigma1_sq / sigma_nsq))

    vifp = num / den

    if numpy.isnan(vifp):
        return 1.0
    else:
        return vifp
结果

运用相同的测试图片,可以得到结果:

VIF: 0.9758460769325894

基于结构信息基础
  • SSIM:根据图像像素间的相关性构造出参考图像与待评图像之间的结构相似性,SSIM 值越大,图像质量越好

PS:至此,找到更合理的代码方法

代码示例
import cv2 as cv
import numpy as np
import math
from skimage.metrics import mean_squared_error
from skimage.metrics import peak_signal_noise_ratio
from skimage.metrics import structural_similarity

# 均方误差(MSE):MSE 的值越小,表明图像质量越好
def get_mse(img1, img2):
    return np.mean((img1 / 255. - img2 / 255.) ** 2)

if __name__ == '__main__':
    origin_img = cv.imread('img.png', 1)
    new_img = cv.imread('denoised_img_noise.png', 1)

    # 均方误差(MSE):MSE 的值越小,表明图像质量越好
    mse = get_mse(origin_img, new_img)
    # 峰值信噪比(PSNR):PSNR 值越大,表明待评图像与参考图像之间的失真较小,图像质量较好
    # 基准为 30dB,小于 30 为劣质
    psnr = peak_signal_noise_ratio(origin_img, new_img)
    # 结构相似度(Structural Similarity,SSIM),SSIM 值越大,图像质量越好
    ssim = structural_similarity(origin_img, new_img, multichannel=True)

    print('MSE:', mse)
    print('PSNR:', psnr)
    print('SSIM:', ssim)
结果

MSE: 0.0004777804926332579

PSNR: 33.20771586094474

SSIM: 0.9570612590498769

存在的问题

我的代码中有这样的一行:from skimage.metrics import mean_squared_error

但是,在下方却没有用到 mean_squared_error 这一函数,这是因为在测试时,使用 mean_squared_error 函数得到的结果(30+)与自己写的 get_mse 函数的结果(0+)大相径庭,而网上的资源大多使用类似于 get_mse 的方法,而对 mean_squared_error 方法所提甚少,且从结果看,MSE 算法的值也是应该越小越好,所以我暂时不使用 mean_squared_error 函数

部分参考

部分参考也成为半参考,它是以理想图像的部分特征信息作为参考,对待评图像进行比较分析,从而得到图像质量评价结果。由于所参考的信息是从图像中提取出来的特征,所以它必须要先提取待评图像和理想图像的部分特征信息,通过比较提取出的部分信息对待评图像进行质量评估。部分参考方法可分为基于原始图像特征方法、基于数字水印方法和基于 Wavelet 域统计模型的方法等。因为部分参考质量评价依赖于图像的部分特征,与图像整体相比而言,数据量下降了很多,目前应用比较集中在图像传输系统中。

这部分内容暂时也没有头绪,先放过

无参考

无参考方法也称为首评价方法,因为一般的理想图像很难获得,所以这种完全脱离了对理想参考图像依赖的质量评价方法应用较为广泛。无参考方法一般都是基于图像统计特性。

  • 均值
  • 标准差
  • 平均梯度
  • 。。。。。。
我的理解

所谓无参考方法,就是只对现有的经过处理的图片进行分析,而不与原图比较。评判方法其实就是是否符合理想图像的特征(与寻找噪声的方式相似:符合噪声特征的像素点就会被判定为噪声)。

个人认为,这样的方法较为适用于无法得到原图,或者原图存在不可忽略的噪声的情况。

正文完
 0
icvuln
版权声明:本站原创文章,由 icvuln 于2021-08-15发表,共计3981字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)